<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Using HashiCorp Vault with Databases</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/vault-datasource" />
  <meta property="og:title" content="Quarkus - Using HashiCorp Vault with Databases" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/vault-datasource">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Using HashiCorp Vault with Databases</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#prerequisites">Prerequisites</a>
<ul class="sectlevel2">
<li><a href="#application">Application</a></li>
</ul>
</li>
<li><a href="#vault-microprofile-config-source">Vault MicroProfile Config Source</a></li>
<li><a href="#credentials-provider">Credentials Provider</a></li>
<li><a href="#dynamic-database-credentials">Dynamic Database Credentials</a></li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>The most common use case when working with Vault is to keep confidential the database connection credentials.
There are several approaches that are supported in Quarkus, with different levels of sophistication
and security:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Property fetched from the KV Secret Engine using the Vault MicroProfile Config Source</p>
</li>
<li>
<p>Quarkus Credentials Provider</p>
</li>
<li>
<p>Vault Dynamic DB Credentials</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This guide aims at providing examples for each of those approaches. We will reuse the application implemented
in the <a href="vault">Vault guide</a> and enhance it with a simple persistence use case.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>This technology is considered preview.</p>
</div>
<div class="paragraph">
<p>In <em>preview</em>, backward compatibility and presence in the ecosystem is not guaranteed.
Specific improvements might require to change configuration or APIs and plans to become <em>stable</em> are under way.
Feedback is welcome on our <a href="https://groups.google.com/d/forum/quarkus-dev">mailing list</a> or as issues in our <a href="https://github.com/quarkusio/quarkus/issues">GitHub issue tracker</a>.</p>
</div>
<div class="paragraph">
<p>For a full list of possible extension statuses, check our <a href="https://quarkus.io/faq/#extension-status">FAQ entry</a>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="prerequisites"><a class="anchor" href="#prerequisites"></a>Prerequisites</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To complete this guide, you need:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>to complete the <a href="vault">Vault guide</a></p>
</li>
<li>
<p>roughly 20 minutes</p>
</li>
<li>
<p>an IDE</p>
</li>
<li>
<p>JDK 1.8+ installed with <code>JAVA_HOME</code> configured appropriately</p>
</li>
<li>
<p>Apache Maven 3.6.2+</p>
</li>
<li>
<p>Docker installed</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="application"><a class="anchor" href="#application"></a>Application</h3>
<div class="paragraph">
<p>We assume the <a href="vault">Vault guide</a> application has been developed, a Vault container is running, and the root token is known.
In this section we are going to start a PostgreSQL database, and add a persistence service in the application.</p>
</div>
<div class="paragraph">
<p>Add the <em>Hibernate</em> and <em>PostgreSQL</em> extensions to the application:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>mvn quarkus:add-extension -Dextensions="io.quarkus:quarkus-hibernate-orm,io.quarkus:quarkus-jdbc-postgresql"</pre>
</div>
</div>
<div class="paragraph">
<p>Create a simple service:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class SantaClausService {

    @Inject
    EntityManager em;

    @Transactional
    public List&lt;Gift&gt; getGifts() {
        return (List&lt;Gift&gt;) em.createQuery("select g from Gift g").getResultList();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>With its <code>Gift</code> entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Entity
public class Gift {

    private Long id;
    private String name;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="giftSeq")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally, add a new endpoint in <code>GreetingResource</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Inject
SantaClausService santaClausService;

@GET
@Path("/gift-count")
@Produces(MediaType.TEXT_PLAIN)
public int geGiftCount() {
    return santaClausService.getGifts().size();
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Start a PostgreSQL database:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name postgres-quarkus-hibernate -e POSTGRES_USER=sarah -e POSTGRES_PASSWORD=connor -e POSTGRES_DB=mydatabase -p 5432:5432 postgres:10.5</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we are ready to configure Vault and Quarkus to be able to connect to this database from the application.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="vault-microprofile-config-source"><a class="anchor" href="#vault-microprofile-config-source"></a>Vault MicroProfile Config Source</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The simplest approach is to write the database password in the KV secret engine under the path that is
fetched from the Vault MicroProfile Config Source.</p>
</div>
<div class="paragraph">
<p>Open a new shell, <code>docker exec</code> in the Vault container and set the root token:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">docker exec -it dev-vault sh
export VAULT_TOKEN=s.5VUS8pte13RqekCB2fmMT3u2</code></pre>
</div>
</div>
<div class="paragraph">
<p>Add a <code>dbpassword</code> property in the <code>config</code> path of the KV secret engine, beside the original <code>a-private-key</code>
property:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">vault kv put secret/myapps/vault-quickstart/config a-private-key=123456 dbpassword=connor</code></pre>
</div>
</div>
<div class="paragraph">
<p>Add the following configuration in Quarkus to use the value of property <code>dbpassword</code> as our database password:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs"># configure your datasource
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = sarah
quarkus.datasource.password = ${dbpassword}
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/mydatabase

# drop and create the database at startup (use `update` to only update the schema)
quarkus.hibernate-orm.database.generation=drop-and-create</code></pre>
</div>
</div>
<div class="paragraph">
<p>Compile and start the application:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">./mvnw package
java -jar target/vault-quickstart-1.0-SNAPSHOT-runner.jar</code></pre>
</div>
</div>
<div class="paragraph">
<p>Test it with the <code>gift-count</code> endpoint:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">curl http://localhost:8080/hello/gift-count</code></pre>
</div>
</div>
<div class="paragraph">
<p>You should see:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">0</code></pre>
</div>
</div>
<div class="paragraph">
<p>This approach is certainly the simplest of all. It has also the big advantage of working with any subsystem
that requires a secret information in the configuration (i.e. not just <em>Agroal</em>).
The only drawback is that the password will never be fetched again from Vault after the initial property loading.
This means that if the db password was changed while running, the application would have to be restarted after
Vault has been updated with the new password.
This contrasts with the credentials provider approach, which fetches the password from Vault every time a connection
creation is attempted.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="credentials-provider"><a class="anchor" href="#credentials-provider"></a>Credentials Provider</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In this approach we introduce a new abstraction called the <em>Credentials Provider</em> that acts as an intermediary
component between the Agroal datasource and Vault. The additional configuration required is small, and it
has the major advantage of handling gracefully database password change while the application is running,
without any restart. Since all new connections go through the <em>Credentials Provider</em> to fetch their password,
we make sure we have a fresh value every time.</p>
</div>
<div class="paragraph">
<p>Create a new path (different than the <code>config</code> path) in Vault where the database password will be added:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">vault kv put secret/myapps/vault-quickstart/db password=connor</code></pre>
</div>
</div>
<div class="paragraph">
<p>Since we allowed read access on <code>secret/myapps/vault-quickstart/*</code> subpaths in the policy, there is nothing else
we have to do to allow the application to read it.</p>
</div>
<div class="paragraph">
<p>When fetching credentials from Vault that are intended to be used by the Agroal connection pool, we need
first to create a named Vault credentials provider in the application.properties:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.vault.credentials-provider.mydatabase.kv-path=myapps/vault-quickstart/db</code></pre>
</div>
</div>
<div class="paragraph">
<p>This defines a credentials provider <code>mydatabase</code> that will fetch the password from key <code>password</code>
at path <code>myapps/vault-quickstart/db</code>.</p>
</div>
<div class="paragraph">
<p>The credentials provider can now be used in the datasource configuration, in place of the <code>password</code>
property:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs"># configure your datasource
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = sarah
quarkus.datasource.credentials-provider = mydatabase
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/mydatabase</code></pre>
</div>
</div>
<div class="paragraph">
<p>Recompile, start and test the <code>gift-count</code> endpoint. You should see <code>0</code> again.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="dynamic-database-credentials"><a class="anchor" href="#dynamic-database-credentials"></a>Dynamic Database Credentials</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The two previous approaches work well and are very popular. However they rely on a well known user configured
in the application (i.e. the database user), and the security comes from the confidentiality of the password.
If the password was stolen, we would have to change it in the database and in Vault. Regulary rotating passwords
is actually a very good practice to limit (in time) the impact of getting the password stolen.</p>
</div>
<div class="paragraph">
<p>A more sophisticated approach consists in letting Vault create and retire database accounts on a regular basis.
This is supported in Vault with the <a href="https://www.vaultproject.io/docs/secrets/databases">Database secret engine</a>. A number
of databases are supported, such as <a href="https://www.vaultproject.io/docs/secrets/databases/postgresql">PostgreSQL</a>.</p>
</div>
<div class="paragraph">
<p>First we need to enable the <code>database</code> secret engine, configure the <code>postgresql-database-plugin</code> and create
the database role <code>mydbrole</code> (replace <code>10.0.0.3</code> by the actual host that is running the PostgreSQL container;
for simplicity we disabled <em>TLS</em> between Vault and the PostgreSQL database):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">vault secrets enable database

vault write database/config/mydb \
    plugin_name=postgresql-database-plugin \
    allowed_roles=mydbrole \
    connection_url=postgresql://{{username}}:{{password}}@10.0.0.3:5432/mydatabase?sslmode=disable \
    username=sarah \
    password=connor

cat &lt;&lt;EOF &gt; vault-postgres-creation.sql
CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO "{{name}}";
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public to "{{name}}";
EOF

vault write database/roles/mydbrole \
    db_name=mydb creation_statements=@vault-postgres-creation.sql \
    default_ttl=1h \
    max_ttl=24h \
    revocation_statements="ALTER ROLE \"{{name}}\" NOLOGIN;" \
    renew_statements="ALTER ROLE \"{{name}}\" VALID UNTIL '{{expiration}}';"</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>For this use case, user <code>sarah</code> configured above needs to be a PostgreSQL super user with the capability
to create users.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Then we need to give a read capability to the Quarkus application on path <code>database/creds/mydbrole</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">cat &lt;&lt;EOF | vault policy write vault-quickstart-policy -
path "secret/data/myapps/vault-quickstart/*" {
  capabilities = ["read"]
}
path "database/creds/mydbrole" {
  capabilities = [ "read" ]
}
EOF</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now that Vault knows how to create users in PostgreSQL, we juste need to change the <code>mydatabase</code> credentials
provider to use a <code>database-credentials-role</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.vault.credentials-provider.mydatabase.database-credentials-role=mydbrole</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>When using <code>quarkus.hibernate-orm.database.generation=drop-create</code>, objects get created with the applicative
user. Since a user will be created every time the applications starts, database objects will be created
with the first created user, then we will attempt to drop them on the second run with a different user that
is not the owner. As expected this will fail. As a result, it is recommended to use
<code>quarkus.hibernate-orm.database.generation=update</code> in this section.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Recompile with <code>./mvnw package</code>, start and test the <code>gift-count</code> endpoint. You should see <code>0</code> again.</p>
</div>
<div class="paragraph">
<p>Notice in the logs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">2020-04-22 14:29:48,522 DEBUG [io.qua.vau.run.VaultDbManager] (Agroal_682171661) generated mydbrole credentials: {leaseId: database/creds/mydbrole/L6PxoI68gZDeVPXP0RAA4c0a, renewable: true, leaseDuration: 60s, valid_until: Wed Apr 22 14:30:48 CEST 2020, username: v-userpass-mydbrole-HeOMJCmy9coEnO2my2AR-1587558588, password:***}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you connect to the PostgreSQL database, and list all users configured on <code>mydatabase</code>, you will see the
<code>sarah</code> super user, but also the technical users dynamically created by Vault:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>docker exec -it postgres-quarkus-hibernate bash
psql mydatabase sarah

mydatabase=# \du
                                                        List of roles
                      Role name                      |                         Attributes                         | Member of
-----------------------------------------------------+------------------------------------------------------------+-----------
 sarah                                               | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 v-userpass-mydbrole-HeOMJCmy9coEnO2my2AR-1587558588 | Password valid until 2020-04-22 12:30:53+00                | {}
 v-userpass-mydbrole-N2ITbBXxoqMQ3A3cZL88-1587558572 | Cannot login                                              +| {}
                                                     | Password valid until 2020-04-22 12:30:37+00                |</pre>
</div>
</div>
<div class="paragraph">
<p>As you can see 2 users have been created:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>v-userpass-mydbrole-N2ITbBXxoqMQ3A3cZL88-1587558572</code> that has expired, which was created while we were executing the tests.</p>
</li>
<li>
<p><code>v-userpass-mydbrole-HeOMJCmy9coEnO2my2AR-1587558588</code> that is valid until <code>12:30:53</code>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>As expected, users have been created dynamically by Vault, with expiration dates, allowing a rotation to occur,
without breaking existing connections, allowing a greater level of security than the traditional
<em>password</em> based approaches.</p>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
